import 'package:flutter/material.dart';
import 'package:zpub_bas/zpub_bas.dart';
import 'package:zpub_ui/com/zerogis/zpubui/tree/bean/node.dart';
import 'package:zpub_ui/com/zerogis/zpubui/tree/constant/TreeConstant.dart';
import 'package:zpub_ui/com/zerogis/zpubui/tree/widget/ImageText.dart';
import 'package:zpub_ui/com/zerogis/zpubui/tree/widget/SearchBar.dart';

/*
 * 树组件
 * 1:树节点中必须包含：'name'(或者'namec'), 'children' 信息，【如果不是则需要替换】
 * 2:树节点中可以包含：'check','icon'信息<br/> 【如果不是则需要替换】
 * 3：注意事项：使用了3张图片：assets/images/member.png，assets/images/expand.png" ， "assets/images/collect.png
 * @param {Object 必传} mOrgans   tree树的数据 mOrgans = [{'name':'空间资源','children':[{'name':'机房','check':true,'icon':1024,'children':[]}]}]
 * @param {Object 选传} onTap     tree的点击事件
 * @param {Object 选传} height    树组件高度
 * @param {Object 选传} expand    是否全部展开，默认不展开
 * @param {Object 选传} mTextSize 文本大小
 * 需要传入的键：<br/>
 * 传入的值类型： <br/>
 * 传入的值含义：<br/>
 * 是否必传 ：
 */
class Tree extends StatefulWidget
{
  /*
   * tree的点击事件
   */
  final ValueChanged<dynamic> onTap;

  /*
   * tree树的数据
   */
  final List<dynamic> mOrgans;

  /*
   * 组件高度
   */
  double height;

  /*
   * 是否全部展开，默认不展开
   */
  bool expand;

  /*
   * 文本大小
   */
  double mTextSize;

  Tree(this.mOrgans, {this.onTap, this.height: double.infinity, Key key, this.mTextSize = 14}) : super(key: key);

  @override
  State<StatefulWidget> createState()
  {
    return TreeState();
  }
}

class TreeState extends State<Tree>
{
  ///保存所有数据的List
  List<Node> mList = <Node>[];

  ///保存当前展示数据的List
  List<Node> mExpand = <Node>[];

  ///保存List的下标的List，用来做标记用
  List<int> mMark = <int>[];

  ///第一个节点的index
  int mNodeId = 1;

  ///展示搜索结构
  bool mShowSearch = false;
  List<Node> mKeep;

  @override
  void initState()
  {
    super.initState();
    mNodeId = 1;
    _parseOrgans(widget.mOrgans);
    _addRoot();
    _expandFirst();
  }

  @override
  Widget build(BuildContext context)
  {
    return Container(child: SafeArea(child: Scaffold(
      backgroundColor: Colors.white,
      body: Column(
        children: <Widget>[
          SearchBar(mList, _onSearch),
          Expanded(child: ListView(
            children: _buildNode(mExpand),
          ),),
        ],
      ),
    )), height: widget.height,);
  }

  ///搜索结果
  void _onSearch(List<Node> result)
  {
    setState(()
    {
      if (result == null)
      { //如果为空，代表搜索关键字为空
        mShowSearch = false;
        mExpand = mKeep; //将之前保存的状态还原
      }
      else
      {
        if (!mShowSearch)
        { //如果之前展示的不是搜索的结果，保存状态，为了之后状态还原做准备
          mKeep = mExpand;
        }
        mShowSearch = true; //展示搜索结果
        mExpand = result;
      }
    });
  }

  ///如果解析的数据是一个list列表，采用这个方法
  void _parseOrgans(List<dynamic> organs)
  {
    for (dynamic organ in organs)
    {
      _parseOrgan(organ);
    }
  }

  ///递归解析原始数据，将organ递归，记录其深度，nodeID和fatherID，将根节点的fatherID置为-1，
  ///保存原始数据为泛型T
  void _parseOrgan(dynamic organ, {int depth = 0, int fatherId = -1})
  {
    int currentId = mNodeId;
    mList.add(Node(false, depth, Node.typeOrgan, mNodeId++, fatherId, organ));

    if (!CxTextUtil.isEmptyList(organ[TreeConstant.CHILDREN]))
    {
      organ[TreeConstant.CHILDREN].forEach((children)
      {
        _parseOrgan(children, depth: depth + 1, fatherId: currentId);
      });
    }
  }

  ///扩展机构树：id代表被点击的机构id
  /// 做法是遍历整个list列表，将直接挂在该机构下面的节点增加到一个临时列表中，
  ///然后将临时列表插入到被点击的机构下面
  void _expand(int id)
  {
    //保存到临时列表
    List<Node> tmp = <Node>[];
    for (Node node in mList)
    {
      if (node.mFatherId == id)
      {
        tmp.add(node);
      }
    }
    //找到插入点
    int index = -1;
    int length = mExpand.length;
    for (int i = 0; i < length; i++)
    {
      if (id == mExpand[i].mNodeId)
      {
        index = i + 1;
        break;
      }
    }
    //插入
    mExpand.insertAll(index, tmp);
  }

  ///收起机构树：id代表被点击的机构id
  /// 做法是遍历整个expand列表，将直接和间接挂在该机构下面的节点标记，
  ///将这些被标记节点删除即可，此处用到的是将没有被标记的节点加入到新的列表中
  void _collect(int id)
  {
    //清楚之前的标记
    mMark.clear();
    //标记
    _mark(id);
    //重新对expand赋值
    List<Node> tmp = <Node>[];
    for (Node node in mExpand)
    {
      if (mMark.indexOf(node.mNodeId) < 0)
      {
        tmp.add(node);
      }
      else
      {
        node.mExpand = false;
      }
    }
    mExpand.clear();
    mExpand.addAll(tmp);
  }

  ///标记，在收起机构树的时候用到
  void _mark(int id)
  {
    for (Node node in mExpand)
    {
      if (id == node.mFatherId)
      {
        if (node.mType == Node.typeOrgan)
        {
          _mark(node.mNodeId);
        }
        mMark.add(node.mNodeId);
      }
    }
  }

  ///增加根
  void _addRoot()
  {
    for (Node node in mList)
    {
      if (node.mFatherId == -1)
      {
        mExpand.add(node);
      }
    }
  }

  /// 展开第一层
  _expandFirst()
  {
    if (!CxTextUtil.isEmptyList(mList))
    {
      mList.first.mExpand = true;
      _expand(mList.first.mNodeId);
    }
  }

  ///构建元素
  List<Widget> _buildNode(List<Node> nodes)
  {
    List<Widget> widgets = List();
    if (nodes != null && nodes.length > 0)
    {
      for (Node node in nodes)
      {
        // 取ImageText组件的image路径和是否隐藏switch控件
        String image;
        bool switchOffstage = true;
        if (CxTextUtil.isEmptyList(node.mObject[TreeConstant.CHILDREN]))
        {
          image =
          node.mObject[TreeConstant.ICON] == null ? "assets/images/member.png" : 'assets/images/layer/${node
              .mObject[TreeConstant.ICON]}.png';
          switchOffstage = false;
        }
        else
        {
          image = node.mExpand ? "assets/images/expand.png" : "assets/images/collect.png";
          switchOffstage = true;
        }

        // 取ImageText组件的image路径
        String title = node.mObject[TreeConstant.NAMEC];
        if (CxTextUtil.isEmpty(title))
        {
          title = node.mObject[TreeConstant.NAME];
        }

        widgets.add(GestureDetector(
          child: ImageText(
            image,
            title,
            mPadding: mShowSearch ? 0 : node.mDepth * 20.0,
            mTextSize: widget.mTextSize,
            switchOffstage: switchOffstage,
            switchChecked: node.mObject[TreeConstant.CHECK] ?? false,
            onChange: switchOffstage ? null : (value)
            {
              node.mObject[TreeConstant.CHECK] = value;
              doClickListItem(node);
            },
          ),
          onTap: ()
          {
            doClickListItem(node);
          },
        ));
      }
    }
    return widgets;
  }


  /*
   * 条目点击事件
   * @param node 树的节点对象
   */
  void doClickListItem(node)
  {
    if (node.mType == Node.typeOrgan)
    {
      if (node.mExpand)
      { //之前是扩展状态，收起列表
        node.mExpand = false;
        _collect(node.mNodeId);
      }
      else
      { //之前是收起状态，扩展列表
        node.mExpand = true;
        _expand(node.mNodeId);
      }
      setState(()
      {});
    }
    if (CxTextUtil.isEmptyList(node.mObject[TreeConstant.CHILDREN]) || !node.mExpand)
    {
      widget.onTap(node);
    }
  }
}
